//
//  LcSubclassAdapter.m
//  18Birdies
//
//  Created by Lc on 15/3/17.
//  Copyright (c) 2015年 Lc. All rights reserved.
//

#import "LcJson.h"
#import "LcJsonException.h"
#import "LcSubclassAdapter.h"

@implementation LcSubclassAdapter

+ (LcSubclassAdapter*)subclassAdapterWithDefaultSubclassType:
    (NSString*)defaultSubclassType {
  LcSubclassAdapter* subclassAdapter = [[self alloc] init];
  subclassAdapter.defaultSubclassType = defaultSubclassType;
  return subclassAdapter;
}

- (id)serialize:(id)object
 ofDeclaredType:(NSString*)declaredType
     withLcJson:(LcJson*)lcJson {
  // pass original class as declared type
  NSString* realType = NSStringFromClass([object class]);
  id jsonElement =
      [lcJson toJsonElement:object
             ofDeclaredType:realType
           withGenericTypes:nil
            skipTypeAdapter:[realType isEqualToString:declaredType]];
  if (![jsonElement isKindOfClass:NSMutableDictionary.class]) {
    @throw [LcJsonException
        exceptionWithReason:
            [NSString stringWithFormat:@"jsonElement should be dictionary in "
                                       @"subclass adapter for type %@",
                                       declaredType]];
  }
  NSMutableDictionary* dictionary = jsonElement;
  dictionary[@"_TYPE"] = realType;
  return dictionary;
}

- (id)deserialize:(id)jsonElement
           ofType:(NSString*)type
       withLcJson:(LcJson*)lcJson {
  if (![jsonElement isKindOfClass:NSDictionary.class]) {
    @throw [LcJsonException
        exceptionWithReason:
            [NSString stringWithFormat:@"jsonElement should be dictionary in "
                                       @"subclass adapter for type %@",
                                       type]];
  }
  NSDictionary* dictionary = (NSDictionary*)jsonElement;
  NSString* subclassType = dictionary[@"_TYPE"];
  if (subclassType == nil) {
    subclassType = self.defaultSubclassType;
  }
  if (subclassType == nil) {
    @throw [LcJsonException
        exceptionWithReason:
            [NSString
                stringWithFormat:@"no subclass type found for type %@", type]];
  }
  Class subclazz = NSClassFromString(subclassType);
  if (subclazz == NULL) {
    @throw [LcJsonException
        exceptionWithReason:[NSString stringWithFormat:@"subclass type not "
                                                       @"valid for type %@, "
                                                       @"subclass type %@",
                                                       type, subclassType]];
  }
  return [lcJson fromJsonElement:jsonElement
                          toType:subclassType
                withGenericTypes:nil
                 skipTypeAdapter:[subclassType isEqualToString:type]];
}

@end
